package com.lz.service.security.config;

import com.lz.common.annotation.AnonymousAccess;
import com.lz.common.utils.ReqMapperUtil;
import com.lz.filter.bootOnceFilter.LzOncePerRequestFilter;
import com.lz.service.security.config.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.List;

@Configuration
//@EnableWebSecurity
//@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter implements UserDetailsService {
    //todo 第一步：实现查询用户信息 - -  返回的UserDetail会经常使用
    //todo 第二步：使用密码加密器  - - 未使用加密器，需要在数据库中的密码前缀添加“{noop}”  每次生成的密码都不一样 所以数据库的密码也不是唯一的  与之相反的是JWT 它每次加解密都是固定的
    //todo 第三步：放行一个用户的登录接口

    @Resource
    private UserMapper userMapper;

    @Value("${spring.profiles.active}")
    private String activeProfile;
    @Resource
    private LzOncePerRequestFilter lzOncePerRequestFilter;

//    @Override
//    protected void configure(HttpSecurity http) throws Exception {
//        http
//                // 禁用CSRF
//                .csrf().disable()
//
//                // 无状态Session
//                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
//
//                // 授权配置
//                .authorizeRequests()
//                // 静态资源放行
//                .antMatchers("/", "/favicon.ico", "/**/*.html", "/**/*.css", "/**/*.js", "/swagger-ui/**", "/swagger-resources/**", "/v3/api-docs/**").permitAll()
//                // 放行所有标记@AnonymousAccess的接口
////                .antMatchers(getAnonymousAccessUrls().toArray(new String[0])).permitAll()
//                .antMatchers("/api/v1/login", "/api/v1/register").permitAll()
//                // 其他所有请求需要认证
//                .anyRequest().authenticated().and();
//
//        // 如果需要添加自定义过滤器
//        // http.addFilterBefore(securityFilter, UsernamePasswordAuthenticationFilter.class);
//    }

    /**
     * 根据用户名查询用户以及对应的权限信息
     * 封装成UserDetails对象返回
     *
     * @param username 用户名
     * @return UserDetails (封装整个用户信息，然后完善接口)
     * @throws UsernameNotFoundException
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User userByUsername = userMapper.getUserByUsername(username);
        MyUserDetails myUserDetails = new MyUserDetails(userByUsername);
        return myUserDetails;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                // 禁用CSRF
                .csrf().disable()

                // 无状态Session
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()

                // 授权配置
                .authorizeRequests()
                // 静态资源放行
                .antMatchers(
                        "/",
                        "/favicon.ico",
                        "/**/*.html",
                        "/**/*.css",
                        "/**/*.js",
                        "/swagger-ui/**",
                        "/swagger-resources/**",
                        "/v3/api-docs/**"
                ).permitAll()

                // 放行所有标记@AnonymousAccess的接口
                .antMatchers("/security/login").permitAll()

                // 其他所有请求需要认证
                .anyRequest().authenticated()
                .and();
        http.addFilterBefore(lzOncePerRequestFilter, UsernamePasswordAuthenticationFilter.class);

        // 如果需要添加自定义过滤器
        // http.addFilterBefore(securityFilter, UsernamePasswordAuthenticationFilter.class);
    }

    /**
     * 在user登录的时候调用，可以调用loadUserByUsername方法获取用户信息
     *
     * @return
     * @throws Exception
     */
    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    /**
     * 没有这个密码工具会，使用默认的加密方法。即在数据库中的密码需要有一个古荡的前缀{noop}
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

}